// 模板方法模式
package main

import "fmt"

type Beverage interface {
	// BoilWater 煮开水
	BoilWater()
	// Brew 冲泡
	Brew()
	// PourInCup 倒入杯中
	PourInCup()
	// AddThings 添加小料
	AddThings()
}

// 封装一套流程模板基类，让具体的制作流程继承且实现
type template struct {
	b Beverage
}

// MakeBeverage 封装的固定模板，制作饮料
func (t *template) MakeBeverage() {
	if t.b == nil {
		return
	}
	// 固定的流程
	t.b.BoilWater()
	t.b.Brew()
	t.b.PourInCup()
	t.b.AddThings()
}

// 具体实现类

type MakeTea struct {
	template
}

func (t *MakeTea) BoilWater() {
	fmt.Println("煮开水")
}
func (t *MakeTea) Brew() {
	fmt.Println("冲泡")
}
func (t *MakeTea) PourInCup() {
	fmt.Println("倒入杯中")
}
func (t *MakeTea) AddThings() {
	fmt.Println("添加小料")
}

func NewMakeTea() *MakeTea {
	makeTea := &MakeTea{}
	makeTea.b = makeTea // 将当前对象赋值给模板中的接口字段，用于后续模板方法调用
	return makeTea
}

func main() {
	makeTea := NewMakeTea()
	makeTea.MakeBeverage()
}
